package chapter9.exercise2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 设计一个生产电脑和搬运电脑类，要求生产出一台电脑就搬走一台电脑，如果没有新的电脑生产
 * 出来，则搬运工要等待新电脑产出；如果生产出的电脑没有搬走，则要等待电脑搬走之后再生产，
 * 并统计出生产的电脑数量
 * @author libojuve@gmail.com
 *
 */
public class Exercise2 {

	public static void main(String[] args) {
		Lock lock = new ReentrantLock();
		Condition cond = lock.newCondition();
		State state = new State();

		Producer prod = new Producer(state, lock, cond);
		Thread tProducer = new Thread(prod);

		Transporter trans = new Transporter(state, lock, cond);
		Thread tTransporter = new Thread(trans);

		tProducer.start();
		tTransporter.start();
	}
}

class State {
	private boolean full;

	public State() {
		full = false;
	}

	public State(boolean full) {
		this.full = full;
	}

	public boolean isFull() {
		return full;
	}

	public void setFull(boolean full) {
		this.full = full;
	}
}

class Producer implements Runnable {

	private int nbProduced;
	private State state;
	private Lock lock;
	private Condition cond;

	public Producer(State state, Lock lock, Condition cond) {
		nbProduced = 0;
		this.state = state;
		this.lock = lock;
		this.cond = cond;
	}

	@Override
	public void run() {
		try {
			while (nbProduced < 10) {
				try {
					lock.lock();
					while (state.isFull()) {
						System.out.println("producer: 已经满了，我得等会儿");
						cond.await();
					}
					// 空啦
					++nbProduced;
					System.out.println("已经生产" + nbProduced + "台电脑啦");
					state.setFull(true);
					cond.signalAll();
				}
				finally {
					lock.unlock();
				}

			}
			System.out.println("已经生产10台电脑了，结束。。。");
		}
		catch (InterruptedException e) {
			System.out.println("Producer进程被中断，结束了。。。");
		}

	}



}

class Transporter implements Runnable {

	private int nbTransported;
	private State state;
	private Lock lock;
	private Condition cond;

	public Transporter(State state, Lock lock, Condition cond) {
		nbTransported = 0;
		this.state = state;
		this.lock = lock;
		this.cond = cond;
	}

	@Override
	public void run() {
		try {
			while (nbTransported < 10) {
				try {
					lock.lock();
					while (!state.isFull()) {
						System.out.println("没东西可搬，得先等会儿");
						cond.await();
					}
					//
					++nbTransported;
					System.out.println("已经搬运" + nbTransported + "台电脑啦");
					state.setFull(false);
					cond.signalAll();
				}
				finally {
					lock.unlock();
				}
			}
			System.out.println("已经搬了10台电脑了，结束了。。。");
		}
		catch (InterruptedException e) {
			System.out.println("Transporter进程被中断，结束了。。。");
		}
	}

}